﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKLoopSearch;

public class FlatPlateFloorRegionCellsOper
{
	private static double mmToFeet(double mm)
	{
		return mm * 0.0032808399;
	}

	private static XYZ ProjectOnto(Plane plane, XYZ p)
	{
		XYZ xyz = p - plane.Origin;
		double num = plane.Normal.DotProduct(xyz);
		return p - num * plane.Normal;
	}

	private static Curve GetProjectSegCurve(Plane plane, Curve cv)
	{
		if (cv is Line)
		{
			XYZ xyz = cv.GetEndPoint(0);
			XYZ xyz2 = cv.GetEndPoint(1);
			xyz = FlatPlateFloorRegionCellsOper.ProjectOnto(plane, xyz);
			xyz2 = FlatPlateFloorRegionCellsOper.ProjectOnto(plane, xyz2);
			return Line.CreateBound(xyz, xyz2);
		}
		if (cv is Arc)
		{
			XYZ xyz3 = cv.GetEndPoint(0);
			XYZ xyz4 = cv.GetEndPoint(1);
			double parameter = cv.Project(xyz3).Parameter;
			double parameter2 = cv.Project(xyz4).Parameter;
			double num = (parameter + parameter2) * 0.5;
			XYZ xyz5 = cv.Evaluate(num, false);
			xyz3 = FlatPlateFloorRegionCellsOper.ProjectOnto(plane, xyz3);
			xyz4 = FlatPlateFloorRegionCellsOper.ProjectOnto(plane, xyz4);
			xyz5 = FlatPlateFloorRegionCellsOper.ProjectOnto(plane, xyz5);
			return Arc.Create(xyz3, xyz4, xyz5);
		}
		return null;
	}

    private static GraphicsStyle GetLineStyle(Autodesk.Revit.DB.Document doc, string strLineTypeName, Autodesk.Revit.DB.Color color, int iLineWeight = 5)
	{
		Category category = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
		if (category == null)
		{
			return null;
		}
		if (!category.SubCategories.Contains(strLineTypeName))
		{
			Transaction transaction = new Transaction(doc, "new line style");
			try
			{
				transaction.Start();
				Category category2 = doc.Settings.Categories.NewSubcategory(category, strLineTypeName);
				category2.LineColor = color;
				category2.SetLineWeight(iLineWeight, (Autodesk.Revit.DB.GraphicsStyleType)1);
				transaction.Commit();
			}
			catch (Exception)
			{
				if (transaction != null && transaction.HasStarted() && !transaction.HasEnded())
				{
					transaction.RollBack();
				}
				return null;
			}
		}
		foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(GraphicsStyle)))
		{
			GraphicsStyle graphicsStyle = element as GraphicsStyle;
			if (graphicsStyle != null && graphicsStyle.Name.CompareTo(strLineTypeName) == 0)
			{
				return graphicsStyle;
			}
		}
		return null;
	}

	private static ModelCurve CreateModelCv(Autodesk.Revit.DB.Document doc, Curve cv, SketchPlane sketchPl, GraphicsStyle lineStyle)
	{
		ModelCurve modelCurve = null;
		Transaction transaction = new Transaction(doc, "CreateModelCv");
		try
		{
			transaction.Start();
			modelCurve = doc.Create.NewModelCurve(cv, sketchPl);
			modelCurve.LineStyle = lineStyle;
			transaction.Commit();
		}
		catch (Exception)
		{
			transaction.RollBack();
		}
		return modelCurve;
	}

	public static List<List<Curve>> GetFlatPlateFloorRegionCellsByDoc(Autodesk.Revit.DB.Document docCur, List<Grid> lstGrids, List<FamilyInstance> lstColumns, List<CurveLoop> loops)
	{
		List<List<Curve>> result = new List<List<Curve>>();
		try
		{
			double num = 0.0;
			XYZ basisZ = XYZ.BasisZ;
			Plane plane = UnifiedModified.CreatePlane(basisZ, XYZ.Zero + basisZ * num);
			List<Curve> list = new List<Curve>();
			foreach (Grid grid in lstGrids)
			{
				Curve curve = grid.Curve;
				if (!(curve == null))
				{
					Curve projectSegCurve = FlatPlateFloorRegionCellsOper.GetProjectSegCurve(plane, curve);
					List<FlatPlateFloorRegionCellsOper.CurveParamPoint> list2 = new List<FlatPlateFloorRegionCellsOper.CurveParamPoint>();
					for (int i = 0; i < lstColumns.Count; i++)
					{
						LocationPoint locationPoint = lstColumns[i].Location as LocationPoint;
						XYZ xyz = new XYZ(locationPoint.Point.X, locationPoint.Point.Y, num);
						IntersectionResult intersectionResult = projectSegCurve.Project(xyz);
						if (intersectionResult.Distance - FlatPlateFloorRegionCellsOper.dMaxDist2Grid <= 1E-06 && projectSegCurve.IsInside(intersectionResult.Parameter))
						{
							list2.Add(new FlatPlateFloorRegionCellsOper.CurveParamPoint(xyz)
							{
								ParamOnCurve = intersectionResult.Parameter
							});
						}
					}
					list2.Sort(new FlatPlateFloorRegionCellsOper.CurveParamPointComparer());
					for (int j = 0; j <= list2.Count - 2; j++)
					{
						FlatPlateFloorRegionCellsOper.CurveParamPoint curveParamPoint = list2[j];
						FlatPlateFloorRegionCellsOper.CurveParamPoint curveParamPoint2 = list2[j + 1];
						if (curveParamPoint.DistanceTo(curveParamPoint2) - FlatPlateFloorRegionCellsOper.dMaxDistColumns <= 1E-06)
						{
							try
							{
								Line item = Line.CreateBound(curveParamPoint, curveParamPoint2);
								list.Add(item);
							}
							catch
							{
							}
						}
					}
				}
			}
			List<Pole2D> list3 = new List<Pole2D>();
			foreach (Curve curve2 in list)
			{
				Pole2D item2 = Pole2D.TransformWallToStructure2DPole(curve2, ElementId.InvalidElementId, 0.0, 0.0);
				list3.Add(item2);
			}
			result = new StructureLoopSearcher(docCur).GetCellsEdgeLoops(list3, true);
		}
		catch
		{
		}
		return result;
	}

	private static double dMaxDistColumns = FlatPlateFloorRegionCellsOper.mmToFeet(12000.0);

	private static double dMaxDist2Grid = FlatPlateFloorRegionCellsOper.mmToFeet(600.0);

	private class CurveParamPoint : XYZ
	{
		public CurveParamPoint(XYZ ptOnCurve) : base(ptOnCurve.X, ptOnCurve.Y, ptOnCurve.Z)
		{
		}

		public double ParamOnCurve { get; set; }
	}

	private class CurveParamPointComparer : IComparer<FlatPlateFloorRegionCellsOper.CurveParamPoint>
	{
		public int Compare(FlatPlateFloorRegionCellsOper.CurveParamPoint x, FlatPlateFloorRegionCellsOper.CurveParamPoint y)
		{
			if (Math.Abs(x.ParamOnCurve - y.ParamOnCurve) <= FlatPlateFloorRegionCellsOper.CurveParamPointComparer.dEpsilon)
			{
				return 0;
			}
			if (y.ParamOnCurve - x.ParamOnCurve > FlatPlateFloorRegionCellsOper.CurveParamPointComparer.dEpsilon)
			{
				return -1;
			}
			return 1;
		}

		public static double dEpsilon = 1E-06;
	}
}
